<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class Entity_Core {

    protected $_data = array();
    protected $_isDeleted = false;
    protected $_isDataChanged = false;
	
    // descendant class init this value
    protected $_idFieldName = null;
    protected $_entityName = null;
    protected $_resource = null;
    
	public function __construct() {	}
	
    public function getData($key=null) {
		if (!$key) 
			return $this->_data;
		else
			return isset($this->_data[$key]) ? $this->_data[$key] : null;
    }
	
    public function setData($key, $value=null) {
		$this->_data[$key] = $value;
		$this->_isDataChanged = true;
        return $this;
    }

    public function addData($data) {
    	$this->_data = array_merge($this->_data, $data);
    	return $this;
    }
    
    public function __call($method, $args) {
        $key = underscore(substr($method,3));
    	
        switch (substr($method, 0, 3)) {
            case 'get' :
                $data = $this->getData($key, isset($args[0]) ? $args[0] : null);
                return $data;

            case 'set' :
                $result = $this->setData($key, isset($args[0]) ? $args[0] : null);
                return $result;

            case 'has' :
                return isset($this->_data[$key]);
        }
        throw new Exception("Invalid method ".get_class($this)."::".$method."(".print_r($args,1).")");
    }

    public function load($id) {
    	if (!$this->_resource) return $this;
    	$db = $this->_resource;
    	$db->from($this->getEntityName())->where($this->getIdFieldName(), $id);
    	$query = $db->get();
    	if ($query->num_rows()!=1) return false;

    	$row = $query->result_array();
		$this->addData($row[0]);
    	return true;
    }
    
    public function save() {
    	if (!$this->_resource) return $this;
    	if (!$this->_isDeleted && !$this->_isDataChanged) return $this;
    	$db = $this->_resource;
    	$result = true;
    	try {
    		if ($this->getId()) {	// perform update
	    		$db->where($this->getIdFieldName(), $this->getId());
				$db->update($this->getEntityName(), $this->getData()); 
    		} else { // insert
				$db->insert($this->getEntityName(), $this->getData()); 
    		}
    	} catch (Exception $e) {
    		$result = false;
    	}
		return $result;
    }
    
    public function delete() {
    	if (!$this->_resource || !$this->getId()) return false;
    	$db = $this->_resource;
    	$db->delete($this->getEntityName(), array($this->getIdFieldName() => $this->getId())); 
		$this->_isDeleted = true;
		return true;
    }
    
    public function getIdFieldName() {
        return $this->_idFieldName;
    }

    public function getEntityName() {
        return $this->_entityName;
    }

    public function getId() {
        if ($this->getIdFieldName()) {
            return $this->getData($this->getIdFieldName());
        }
        return $this->getData('id');
    }
	
    public function getResource() {
    	return $this->_resource;
    }

    public function getCollection() {
    	$path = str_replace('Entity_', '', get_class($this)).'/Collection.php';
    	if (file_exists(__DIR__ . $path)) {
			$class = $class.'_Collection';
    	} else {
	    	$path = 'Core/Collection.php';
	    	$class = 'Entity_Core_Collection';
    	}

    	require_once($path);
		$result = new $class();
		return $result->setEntity($this);
    }
    
	public function createEntity($data) {
		$class = get_class($this);
		$result = new $class();
		$result->_resource = $this->_resource;
		return $result->addData($data);
	}
}

